#ifndef BACKEND_H
#define BACKEND_H
#include "GlobalConfig.h"
#include <wx/thread.h>
#include <wx/string.h>
#include <wx/event.h>
#include <vector>

#define THREADMAN \
    ThreadManager::GetInstance()

wxDECLARE_EVENT(EVT_GET_PIN_DONE, wxThreadEvent);
wxDECLARE_EVENT(EVT_LOGIN_DONE, wxThreadEvent);
wxDECLARE_EVENT(EVT_CF_SYNC_DONE, wxThreadEvent);

class wxEvtHandler;

class ThreadManager
{
    private:
    std::vector<wxThread*> threadsList;
    wxCriticalSection threadsList_CS;

    ThreadManager();
    virtual ~ThreadManager();

    public:
    static ThreadManager& GetInstance();

    void RegThread(wxThread* pThread);
    void UnregThread(wxThread* pThread);
    void cleanAllThreads();
};

class CLogin;

class BackendWorker_GetPIN : public wxThread
{
    public:
        BackendWorker_GetPIN(wxEvtHandler* mainThread_handler, wxCriticalSection* dataCS_handler);
        virtual ~BackendWorker_GetPIN();

        bool startWorking(CLogin* pLogin);
    private:
        wxEvtHandler* m_pMainThread;
        wxCriticalSection* m_pCLoginMainThreadCS; // no need to use this global CS. CLogin has its primitive CS locker
        CLogin*             m_pLogin;
        virtual wxThread::ExitCode Entry();
};

class BackendWorker_Login : public wxThread
{
    public:
        BackendWorker_Login(wxEvtHandler* mainThread_handler, wxCriticalSection* dataCS_handler);
        virtual ~BackendWorker_Login();

        bool startWorking(CLogin* pLogin, const wxString& PIN);
    private:
        wxEvtHandler* m_pMainThread;
        wxCriticalSection* m_pCLoginMainThreadCS; // no need to use this global CS. CLogin has its primitive CS locker
        CLogin*             m_pLogin;
        wxString            m_PIN;
        virtual wxThread::ExitCode Entry();
};


class CFollowersQueryInc;

class BackendWorker_CFsync : public wxThread
{
    public:
        BackendWorker_CFsync(wxEvtHandler* mainThread_handler, wxCriticalSection* dataCS_handler);
        virtual ~BackendWorker_CFsync();

        bool startWorking(CFollowersQueryInc* CF_in, wxString& userId_in);

        enum resultType
        {
            INIT_RECORD_DATA_OK = 0,
            FIND_UNFOLLOWED_OK,
            UPDATE_NEW_FOLLOWED_OK,
            FINAL_OK,
            HAS_ANY_ERROR,
            NOTHING_MORE
        };

    private:
        wxEvtHandler* m_pMainThread;
        wxCriticalSection* m_pCFMainThreadCS; // To prevent CF is accessed from main thread
        CFollowersQueryInc* m_CF;
        wxString m_userID;
        int8_t resultFlag;
        virtual wxThread::ExitCode Entry();
};
#endif // BACKEND_H
